package Verifier;



import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.math.BigInteger;

/**
 * This class contains service functions that converting 
 * different data types such as integer, string, file and byte array.
 * @author Hadar Miller and Or Stern
 *
 */
public class GeneralUtil {
	
	/**
	 * read ASCII string from file
	 * 
	 * @param file File to convert.
	 * @return  The string representing the content of the file. 
	 * @throws IOException Reading the file failed.
	 */
	public static String fileToString(File file) throws IOException {
		 BufferedReader br = new BufferedReader(new FileReader(file));
		        StringBuilder sb = new StringBuilder();
		        String line = br.readLine();
		
		        while (line != null) {
		            sb.append(line);
		            sb.append("\n");
		            line = br.readLine();
		        }
		        String everything = sb.toString();
		        br.close();
		    if (everything.length() == 0)
		    	return "";
		        
		    return everything.substring(0, everything.length() - 1);
	}
	
	/**
	 * Convert the string into an array of bytes while treating the string as an hexa string. 
	 * @param s The string to convert.
	 * @return Array of bytes representing the string.
	 * @throws Exception Conversion failed
	 */
	public static byte[] hexStringToByteArray(String s) throws Exception {
	    int len = s.length();
	    if ((len % 2) != 0)
	    	throw new Exception("seed length must be even");
	    byte[] data = new byte[len / 2];
	    for (int i = 0; i < len; i += 2) {
	        data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
	                             + Character.digit(s.charAt(i+1), 16));
	    }
	    return data;
	}
	
	
	/**
	 * Read file into byte array.
	 * @param file File to convert.
	 * @return Array of bytes representing the content of the file.
	 * @throws Exception Reading the file failed.
	 */
	public static byte[] fileToByteArray(File file) throws Exception
	{
		byte[] fileBArray = new byte[(int)file.length()];
		try {			
			FileInputStream  fis= new FileInputStream(file);
			fis.read(fileBArray);
			fis.close();
		} catch (Exception e) {
			throw new Exception("cannot convert the file to byte array\n" + e.getMessage());
		}
		
		return fileBArray;
	}
	
	/**
	 * Convert a byte array to an integer.
	 * @param b Byte array to convert.
	 * @return The integer represented by the byte array.
	 */
	public static int byteArrayToInt(byte[] b) 
	{
	    int value = 0;
	    for (int i = 0; i < 4; i++) {
	        int shift = (4 - 1 - i) * 8;
	        value += (b[i] & 0x000000FF) << shift;
	    }
	    return value;
	}
	
	/**
	 * Convert byte array to hexa string.
	 * @param in Byte array to convert.
	 * @return Hexa string represented by the byte array.
	 */
	public static String byteArrayToHexString(byte in[]) {

		byte ch = 0x00;
		int i = 0;
		if (in == null || in.length <= 0)
		return null;

		String pseudo[] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
		"A", "B", "C", "D", "E", "F" };
		StringBuffer out = new StringBuffer(in.length * 2);

		while (i < in.length) {
		ch = (byte) (in[i] & 0xF0); 
		ch = (byte) (ch >>> 4);

		ch = (byte) (ch & 0x0F);

		out.append(pseudo[ch]); 

		ch = (byte) (in[i] & 0x0F); 
		out.append(pseudo[ch]); 

		i++;
		}
		String rslt = new String(out);
		return rslt;
	}

	/**
	 * Convert integer to an array of bytes
	 * @param x Number to convert.
	 * @return Byte array representing the number x.
	 */
	public static byte[] intToByteArray(int x)
	{
		byte[] output = new byte[4];
		output[0] = (byte)(x >> 24);
		output[1] = (byte)(x >> 16);
		output[2] = (byte)(x >> 8);
		output[3] = (byte)(x /*>> 0*/);
		
		return output;
	}
	
	
	/** convert number into two decimal digits representation */
	/**
	 * Convert number into two decimal digits representation
	 * @param num Number to extend.
	 * @return Two decimal digits representation of the number num.
	 */
	public static String toDecimalString(int num)
	{
		if (num < 10)
			return "0"+num;
		else
			return ""+num;
		
	}
	

	/**
	 * Convert string to byte array representing the corresponding byte tree.
	 * @param str String to convert.
	 * @return A byte array representing the corresponding byte tree (i.e., the data of the leaf is str).
	 * @throws Exception Conversion failed.
	 */
	public static byte[] stringToLeaf(String str) throws Exception
	{
		ByteArrayOutputStream outStream = new ByteArrayOutputStream();
		outStream.write((byte) 0x01);
		byte[] strByte = str.getBytes();
		outStream.write(intToByteArray(strByte.length));
		outStream.write(strByte);
		return outStream.toByteArray();
	}
	
	/**
	 *  Convert integer to byte array representing the corresponding byte tree.
	 * @param num Integer to conbert.
	 * @return A byte array representing the corresponding byte tree (i.e., the data of the leaf is num).
	 * @throws Exception Conversion failed.
	 */
	public static byte[] intToLeaf(int num) throws Exception
	{
		ByteArrayOutputStream outStream = new ByteArrayOutputStream();
		outStream.write((byte) 0x01);
		outStream.write(intToByteArray(4));
		outStream.write(intToByteArray(num));
		return outStream.toByteArray();
	}
}
